package com.droid.customcalendar.cal.model;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import com.droid.customcalendar.cal.util.DateTimeUtils;

/**
 * Create calendar data for a month
 * */
public class MonthCalendarDataGenerator {
	public static final int NUMBER_OF_DAYS_FROM_WEEK = 7;

	private Locale locale;
	private Date crtDate;
	private Calendar cal;
	private int prevMonthDaysToFill;

	public MonthCalendarDataGenerator() {
		this(new Date(), Locale.getDefault());
	}

	public MonthCalendarDataGenerator(Locale locale) {
		this(new Date(), locale);
	}

	public MonthCalendarDataGenerator(Date date, Locale locale) {
		this.locale = locale != null ? locale : Locale.getDefault();
		crtDate = date != null ? date : new Date();
		cal = Calendar.getInstance(locale);
		cal.setTime(crtDate);

		int pos = getFirstDayOfMonthPos();
		int firstDayOfWeek = cal.getFirstDayOfWeek();
		prevMonthDaysToFill = pos >= firstDayOfWeek ? pos - firstDayOfWeek : NUMBER_OF_DAYS_FROM_WEEK - firstDayOfWeek + 1;
	}

	public int getNumberOfWeeks() {
		int totalDays = getCurrentMonthDays() + prevMonthDaysToFill;
		int fullWeeks = totalDays / NUMBER_OF_DAYS_FROM_WEEK;
		int r = totalDays % NUMBER_OF_DAYS_FROM_WEEK;
		return r <= 0 ? fullWeeks : fullWeeks + 1;
	}

	public int getCurrentMonthDays() {
		return cal.getActualMaximum(Calendar.DAY_OF_MONTH);
	}

	/** Return on which day it was first day of the month. */
	public int getFirstDayOfMonthPos() {
		int crtDay = cal.get(Calendar.DAY_OF_MONTH);
		cal.set(Calendar.DAY_OF_MONTH, 1);
		int first = cal.get(Calendar.DAY_OF_WEEK);
		cal.set(Calendar.DAY_OF_MONTH, crtDay);
		cal.setTime(crtDate);
		return first;
	}

	public String getMonthName() {
		return new SimpleDateFormat("MMMM", locale).format(cal.getTime());
	}

	public int getYear() {
		return cal.get(Calendar.YEAR);
	}

	public int getCurrentMonth() {
		return cal.get(Calendar.MONTH);
	}

	public List<String> getDays() {
		List<String> days = new ArrayList<String>();
		int firstDay = cal.getFirstDayOfWeek();
		cal.set(Calendar.DAY_OF_WEEK, firstDay);
		for (int day = firstDay; day < NUMBER_OF_DAYS_FROM_WEEK; day++) {
			days.add(String.format(locale, "%ta", cal));
			cal.add(Calendar.DAY_OF_WEEK, 1);
		}
		for (int i = 0; i < firstDay; i++) {
			days.add(String.format(locale, "%ta", cal));
			cal.add(Calendar.DAY_OF_WEEK, 1);
		}
		cal.setTime(crtDate);
		return days;
	}

	public Date getDate(int row, int col) {
		Calendar firstDayOfMonth = getFirstDayOnMonth();
		int day = row * NUMBER_OF_DAYS_FROM_WEEK + col - prevMonthDaysToFill;
		if (row == 0 && col < prevMonthDaysToFill) {
			int x = -prevMonthDaysToFill + col;
			firstDayOfMonth.add(Calendar.DAY_OF_MONTH, x);
		} else {
			firstDayOfMonth.add(Calendar.DAY_OF_MONTH, day);
		}
		return firstDayOfMonth.getTime();
	}

	private Calendar getFirstDayOnMonth() {
		Calendar firstDayOfMonth = Calendar.getInstance(locale);
		firstDayOfMonth.setTime(cal.getTime());
		firstDayOfMonth.set(Calendar.DAY_OF_MONTH, 1);
		return firstDayOfMonth;
	}

	public String formatDate(Date date) {
		SimpleDateFormat dateFormat = new SimpleDateFormat("dd", locale); // MM-dd-yyyy
		return dateFormat.format(date);
	}

	public int getDatePosition(Date date) {
		Date firstDay = DateTimeUtils.removeTime(getFirstDayOnMonth().getTime(), locale);
		date = DateTimeUtils.removeTime(date, locale);
		long crtTime = date.getTime();
		long firstTime = firstDay.getTime();
		int time = (int) ((crtTime - firstTime) / 86400000);
		time += prevMonthDaysToFill;
		return time;
	}

	public Locale getLocale() {
		return locale;
	}
	
	public Date getCurrentDate() {
		return crtDate;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		int year = getYear();
		int month = getCurrentMonth();
		result = prime * result + month;
		result = prime * result + year;
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		MonthCalendarDataGenerator other = (MonthCalendarDataGenerator) obj;
		if (getCurrentMonth() != other.getCurrentMonth())
			return false;
		if (getYear() != other.getYear())
			return false;
		return true;
	}

	
}
